package com.handle.common.datascope.aspect;

import com.handle.common.core.base.BaseParam;
import com.handle.common.core.constants.ConstantEnums;
import com.handle.common.core.dto.token.User;
import com.handle.common.core.utils.ContextHolderUtils;
import com.handle.common.core.utils.StringUtils;
import com.handle.common.datascope.annotation.DataScope;
import com.handle.system.api.dto.SysRoleDto;
import com.handle.system.api.dto.SysUserDto;
import com.handle.system.api.feign.RemoteSystemUser;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 数据过滤处理
 * @author zhangqing
 */
@Aspect
@Slf4j
@Component
@AllArgsConstructor
public class DataScopeAspect {

    private final RemoteSystemUser remoteSystemUser;

    /**
     * 配置织入点
     */
    @Pointcut("@annotation(com.handle.common.datascope.annotation.DataScope)")
    public void dataScopePointCut() {
    }

    @Before("dataScopePointCut()")
    public void doBefore(JoinPoint point){
        handleDataScope(point);
    }

    private void handleDataScope(final JoinPoint joinPoint) {
        // 获得注解
        DataScope controllerDataScope = getAnnotationLog(joinPoint);
        if (controllerDataScope == null) {
            return;
        }
        // 获取当前的用户
        User userDto = ContextHolderUtils.getCurrentUser();
        if(!StringUtils.isNull(userDto)){
            if (!ContextHolderUtils.isSuperAdmin(userDto)) {
                // 获取用户信息
                SysUserDto sysUserDto = remoteSystemUser.loadByUsername(userDto.getLoginName(), userDto.getTenantCode());
                dataScopeFilter(joinPoint, sysUserDto, controllerDataScope.deptTableAlias(),
                        controllerDataScope.userTableAlias());
            }
        }else {
            log.warn("数据权限拦截失败,执行对象 currentUser is null");
        }
    }

    /**
     * 数据范围过滤
     *
     * @param joinPoint 切点
     * @param sysUserDto      用户
     */
    private static void dataScopeFilter(JoinPoint joinPoint, SysUserDto sysUserDto, String deptAlias, String userAlias) {
        StringBuilder sqlString = new StringBuilder();
        for (SysRoleDto role : sysUserDto.getRoles()) {
            String dataScope = role.getDataScope();
            if (ConstantEnums.DataScope.DATA_SCOPE_ALL.getCode().equals(dataScope)) { // 数据权限为1:全部数据权限
                log.info("数据范围过滤->【查询全部数据权限】");
                sqlString = new StringBuilder();
                break;
            } else if (ConstantEnums.DataScope.DATA_SCOPE_CUSTOM.getCode().equals(dataScope)) { // 数据权限为2: 自定数据权限
                log.info("数据范围过滤->【查询自定数据权限】");
                sqlString.append(StringUtils.format(
                        " OR {}.id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias,
                        role.getId()));
            } else if (ConstantEnums.DataScope.DATA_SCOPE_DEPT.getCode().equals(dataScope)) { // 数据权限为3:部门数据权限
                log.info("数据范围过滤->【查询本部门数据权限】");
                sqlString.append(StringUtils.format(" OR {}.id = {} ", deptAlias, sysUserDto.getDept().getId()));
            } else if (ConstantEnums.DataScope.DATA_SCOPE_DEPT_AND_CHILD.getCode().equals(dataScope)) { //数据权限为4:部门及以下数据权限
                log.info("数据范围过滤->【查询本部门及以下权限】");
                String deptChild = sysUserDto.getDept().getParentId() + "," + sysUserDto.getDept().getId();
                sqlString.append(StringUtils.format(
                        " OR {}.id IN ( SELECT id FROM sys_dept WHERE id = {} or ancestors LIKE '%{}%' )",
                        deptAlias, sysUserDto.getDept().getId(), deptChild));
            } else if (ConstantEnums.DataScope.DATA_SCOPE_SELF.getCode().equals(dataScope)) { //数据权限为5:仅本人数据权限
                log.info("数据范围过滤->【查询仅本人数据权限】");
                if (!StringUtils.isEmpty(userAlias)) {
                    sqlString.append(StringUtils.format(" OR {}.id = {} ", userAlias, sysUserDto.getId()));
                } else {
                    sqlString.append(StringUtils.format(" OR {}.id IS NULL ", deptAlias));
                }
            }
        }
        if (!StringUtils.isEmpty(sqlString.toString())) {
            BaseParam baseParam = (BaseParam) joinPoint.getArgs()[0];
            baseParam.setDataScope(" AND (" + sqlString.substring(4) + ")");
            log.info("数据范围过滤sql->{}",baseParam.getDataScope());
        }
    }

    /**
     * 是否存在注解，如果存在就获取
     */
    private DataScope getAnnotationLog(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        if (method != null) {
            return method.getAnnotation(DataScope.class);
        }
        return null;
    }
}
